﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Quick.Communicator;

namespace SerialPortTool
{    
    public partial class SerialControl : UserControl
    {
        SerialConfig m_SerialConfig = null;

        Quick.Communicator.SuperSerialPort m_SuperSerialPort = null;
        Quick.Communicator.IResolver m_IResolver = null;
        bool IsShowHex = false;
        /// <summary>
        /// 接收事件
        /// </summary>
        public event SerialPortReceiveDataEndEventHandler ReceiveDataEnd;
        public SerialControl()
        {
            InitializeComponent();            
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSetting_Click(object sender, EventArgs e)
        {
            try
            {
                Quick.Communicator.SerialPortConfigFrm frm = new SerialPortConfigFrm(1, m_SerialConfig);
                
                var dr = frm.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    m_SerialConfig = frm.GetConfigs().FirstOrDefault();
                    txtPortName.Text = m_SerialConfig.PortName;
                    if (null != m_SuperSerialPort && m_SuperSerialPort.IsRunning)
                    {
                        m_SuperSerialPort.Stop();
                    }
                }
            }
            catch (Exception ex)
            {  }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (m_SerialConfig == null)
                {
                    MessageBox.Show("请先配置串口参数!");
                    return;
                }
                if (string.IsNullOrEmpty(cboEncoding.Text))
                {
                    MessageBox.Show("请选择编码类型!");
                    return;
                }
                IsShowHex = chkHex.Checked;
                string endTagChar = txtEndChar.Text;
                endTagChar = endTagChar?.Replace("\\n", "\n")
                                       ?.Replace("\\r", "\r")
                                       ?.Replace("\\t", "\t")
                                       ?.Replace("\\v", "\v")
                                       ?.Replace("\\b", "\b")
                                       ?.Replace("\\a", "\a")
                                       ?.Replace("\\f", "\f");
                m_IResolver = new Quick.Communicator.DatagramResolver(Encoding.GetEncoding(cboEncoding.Text), endTagChar, chkHexCar.Checked);
                if (null != m_SuperSerialPort)
                {
                    m_SuperSerialPort.SetParameter(m_SerialConfig.PortName, m_SerialConfig.BaudRate, m_SerialConfig.Parity, m_SerialConfig.DataBits, m_SerialConfig.StopBits, m_IResolver, m_SerialConfig.DTR, m_SerialConfig.RTS);
                    m_SuperSerialPort.Start();
                }
                else
                {
                    m_SuperSerialPort = new Quick.Communicator.SuperSerialPort(m_SerialConfig.PortName, m_SerialConfig.BaudRate, m_SerialConfig.Parity, m_SerialConfig.DataBits, m_SerialConfig.StopBits, m_IResolver, m_SerialConfig.DTR, m_SerialConfig.RTS);
                    m_SuperSerialPort.ReceiveDataEnd += M_SuperSerialPort_ReceiveDataEnd;
                    m_SuperSerialPort.Start();
                }
                SetControlEnable(true);
            }
            catch (Exception ex)
            { }
        }

        private void SetControlEnable(bool isStart)
        {
            btnStart.Enabled =!isStart;
            btnStop.Enabled = isStart;
            btnSetting.Enabled = !isStart;
            cboEncoding.Enabled = !isStart;
            btnSend.Enabled = isStart;
            txtSend.Enabled = isStart;
            chkSendHex.Enabled = isStart;
            txtEndChar.Enabled = !isStart;
            chkHexCar.Enabled = !isStart;
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool SendData(string msg)
        {
            try
            {
                if (m_SuperSerialPort == null)
                {
                    return false;
                }
                bool bl = m_SuperSerialPort.SendData(msg, !string.IsNullOrEmpty(txtEndChar.Text));
                WriteLog($"发送数据:{msg}\r\n抛送结果:{bl.ToString()}");
                return bl;
            }
            catch (Exception ex)
            {
                WriteLog($"异常:SendData " + ex.ToString());
            }
            return false;
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public bool SendData(byte[] bt)
        {
            try
            {
                if (m_SuperSerialPort == null)
                {
                    return false;
                }
                bool bl = m_SuperSerialPort.SendData(bt, !string.IsNullOrEmpty(txtEndChar.Text));
                WriteLog($"发送数据:{ m_IResolver.ByteToHexString(bt, ' ')}\r\n抛送结果:{bl.ToString()}");
                return bl;
            }
            catch (Exception ex)
            {
                WriteLog($"异常:SendData " + ex.ToString());
            }
            return false;
        }
        private void M_SuperSerialPort_ReceiveDataEnd(object obj, Quick.Communicator.SerialPortEventArgs e)
        {
            try
            {
                if (null != ReceiveDataEnd)
                {
                    Delegate[] delegateList = ReceiveDataEnd.GetInvocationList();
                    foreach (SerialPortReceiveDataEndEventHandler handler in delegateList)
                    {
                        handler.BeginInvoke(obj, e, null, null);
                    }
                }
                string msg = null;
                if (IsShowHex)
                {
                    msg = m_IResolver.ByteToHexString(e.DatagramByte, ' ');
                }
                else
                {
                    msg = e.Datagram;
                }
                WriteLog("收到数据:" + msg);
            }
            catch (Exception ex)
            {
                WriteLog($"异常:ReceiveDataEnd " + ex.ToString());
            }
        }

        private void WriteLog(string msg)
        {
            if (!isShowLog)
            {
                return;
            }
            if (rtbMsg.InvokeRequired)
            {
                rtbMsg.BeginInvoke(new Action(() =>
                {
                    try
                    {
                        if (rtbMsg.Lines.Length > 5000)
                        {
                            rtbMsg.Clear();
                        }
                        rtbMsg.AppendText(DateTime.Now.ToString("yyyy-mm-dd HH:mm:ss") + "\r\n" + msg.Trim() + "\r\n\r\n");
                        rtbMsg.ScrollToCaret();
                        rtbMsg.Refresh();
                    }
                    catch (Exception)
                    {  }
                }));
            }
            else
            {
                try
                {
                    if (rtbMsg.Lines.Length > 5000)
                    {
                        rtbMsg.Clear();
                    }
                    rtbMsg.AppendText(DateTime.Now.ToString("yyyy-mm-dd HH:mm:ss") + "\r\n" + msg.Trim() + "\r\n\r\n");
                    rtbMsg.ScrollToCaret();
                    rtbMsg.Refresh();
                }
                catch (Exception ex)
                { }
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (null != m_SuperSerialPort)
            {
                m_SuperSerialPort.Stop();
            }
            SetControlEnable(false);
        }

        private void chkHex_CheckedChanged(object sender, EventArgs e)
        {
            IsShowHex = chkHex.Checked;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtSend.Text.Trim()))
            {
                return;
            }
            if (chkSendHex.Checked)
            {
                try
                {
                    byte[] bt = m_IResolver.HexStringToByte(txtSend.Text.Trim());
                    SendData(bt);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(txtSend.Text.Trim() + "不是有效的HEX 数据包!");
                }
            }
            else
            {
                SendData(txtSend.Text.Trim());
            }
        }
        public void Stop()
        {
            if (null != m_SuperSerialPort)
            {
                m_SuperSerialPort.Stop();
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            rtbMsg.Clear();
        }
        bool isShowLog = true;
        private void chkShowLog_CheckedChanged(object sender, EventArgs e)
        {
            isShowLog = chkShowLog.Checked;
        }
    }
}
